/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vue;

/**
 *
 * @author FM & KB
 */
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import javax.swing.BoundedRangeModel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import librairies.FilterFileChooser;
import librairies.ModelJTableVariable;
import librairies.OutputStreamManager;

public class VueInterpreteur extends JFrame implements ChangeListener {

    private JPanel contentPane;
    private JTextArea txtArea_programme;
    //TODO : a changer
    public static JTextPane txtPane_console;
    private JMenuBar menuBar;
    private JMenu menuBar_file;
    private JMenuItem menuItem_ouvrirFichier;
    private JMenuItem menuItem_exit;
    private JTextArea num_ligne;
    private int num;
    private JTable table_variable;
    private JButton btn_execute;
    private JScrollPane sp; 
    private JScrollPane sp_programme;
    private JScrollPane sp_numLigne;
    private JScrollPane sp_variable;
    private boolean codeModifie = true;
    private Color couleur = Color.black;
    public static String MENU_EXIT = "exit";
    public static String MENU_OPEN_FILE = "open_file";
    public static String BTN_EXECUTE = "execute";


    /**
     * Create the frame.
     */
    public VueInterpreteur() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 536, 405);

        setTitle("iInterpret");

        menuBar = new JMenuBar();
        setJMenuBar(menuBar);

        menuBar_file = new JMenu("File");
        menuBar.add(menuBar_file);

        menuItem_ouvrirFichier = new JMenuItem("Open a Picol file");
        menuItem_ouvrirFichier.setActionCommand(MENU_OPEN_FILE);
        menuBar_file.add(menuItem_ouvrirFichier);

        menuItem_exit = new JMenuItem("Exit");
        menuItem_exit.setActionCommand(MENU_EXIT);
        menuBar_file.add(menuItem_exit);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWidths = new int[]{0, 0, 0, 0, 0};
        gbl_contentPane.rowHeights = new int[]{0, 0, 0, 0, 0};
        gbl_contentPane.columnWeights = new double[]{0.0, 0.0, 0.0, 1.0, 1.0, Double.MIN_VALUE};
        gbl_contentPane.rowWeights = new double[]{0.0, 0.0, 1.0, 1.0, Double.MIN_VALUE};
        contentPane.setLayout(gbl_contentPane);

        btn_execute = new JButton("Execute");
        btn_execute.setActionCommand(BTN_EXECUTE);
        GridBagConstraints gbc_btn_execute = new GridBagConstraints();
        gbc_btn_execute.fill = GridBagConstraints.BOTH;
        gbc_btn_execute.insets = new Insets(0, 0, 5, 5);
        gbc_btn_execute.gridx = 1;
        gbc_btn_execute.gridy = 0;
        contentPane.add(btn_execute, gbc_btn_execute);
		
        txtArea_programme = new JTextArea();
        GridBagConstraints gbc_txtArea_programme = new GridBagConstraints();
        gbc_txtArea_programme.gridheight = 2;
        gbc_txtArea_programme.gridwidth = 3;
        gbc_txtArea_programme.insets = new Insets(0, 0, 5, 0);
        gbc_txtArea_programme.fill = GridBagConstraints.BOTH;
        gbc_txtArea_programme.gridx = 2;
        gbc_txtArea_programme.gridy = 1;
        sp_programme = new JScrollPane(txtArea_programme);
        sp_programme.getVerticalScrollBar().getModel().addChangeListener(this); 
        contentPane.add(sp_programme, gbc_txtArea_programme);
        
        num_ligne = new JTextArea();
        sp_numLigne = new JScrollPane(num_ligne);
        sp_numLigne.getVerticalScrollBar().getModel().addChangeListener(this);   
        GridBagConstraints gbc_num_ligne = new GridBagConstraints();
        gbc_num_ligne.gridheight = 2;
        gbc_num_ligne.insets = new Insets(0, 0, 5, 5);
        gbc_num_ligne.fill = GridBagConstraints.BOTH;
        gbc_num_ligne.gridx = 1;
        gbc_num_ligne.gridy = 1;
        contentPane.add(sp_numLigne, gbc_num_ligne);
        
        table_variable = new JTable();
        GridBagConstraints gbc_table_variable = new GridBagConstraints();
        gbc_table_variable.insets = new Insets(0, 0, 0, 5);
        gbc_table_variable.fill = GridBagConstraints.BOTH;
        gbc_table_variable.gridx = 1;
        gbc_table_variable.gridy = 3;
        
        sp_variable = new JScrollPane(table_variable);
        contentPane.add(sp_variable, gbc_table_variable);


        txtPane_console = new JTextPane();
        JScrollPane sp_console = new JScrollPane(txtPane_console);
        txtPane_console.setEditable(false);
        GridBagConstraints gbc_txtPane_console = new GridBagConstraints();
        gbc_txtPane_console.gridwidth = 3;
        gbc_txtPane_console.fill = GridBagConstraints.BOTH;
        gbc_txtPane_console.gridx = 2;
        gbc_txtPane_console.gridy = 3;
        contentPane.add(sp_console, gbc_txtPane_console);
                
        //On met en place la maj des numéro de lignes avec un DocumentListener
        txtArea_programme.getDocument().addDocumentListener(new DocumentListener() {

            @Override
            public void insertUpdate(DocumentEvent de) {
                majNumLigne();
            }

            @Override
            public void removeUpdate(DocumentEvent de) {
                majNumLigne();
            }

            @Override
            public void changedUpdate(DocumentEvent de) {
                majNumLigne();
            }
        });
    }
   

    public void abonnement(ActionListener al) {
        menuItem_exit.addActionListener(al);
        menuItem_ouvrirFichier.addActionListener(al);
        btn_execute.addActionListener(al);
    }

    public String ouvrirProgramme() {
        String fileName = null;
        JFileChooser chooser = new JFileChooser(".");
        //On limite le choix des fichiers aux .picol avec un FileFilter
        FilterFileChooser filter = new FilterFileChooser("Fichiers picol", ".picol");
        chooser.setFileFilter(filter);
        int returnVal = chooser.showOpenDialog(txtArea_programme);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            fileName = chooser.getSelectedFile().getName();
            ajouterLigneConsole("Ouverture du fichier : " + fileName + "\n", Color.BLACK);
            afficherProgramme(chooser.getSelectedFile().getName());
        }
        return fileName;
    }

    private void afficherProgramme(String fichier) {
        try {
            FileInputStream ips = new FileInputStream(fichier);
            InputStreamReader ipsr = new InputStreamReader(ips);
            BufferedReader br = new BufferedReader(ipsr);
            String ligne, chaine = "";
            while ((ligne = br.readLine()) != null) {
                chaine+=ligne+"\n";
            }
            txtArea_programme.setText(chaine);
            btn_execute.setEnabled(true);
        } catch(Exception e){
            System.out.println(e.getMessage());
        }
    }

    /**
     * @param chaine
     * @param couleur 
     */
    public void ajouterLigneConsole(String chaine, Color couleur) {
        StyledDocument doc = (StyledDocument) txtPane_console.getDocument();
        try {
            this.couleur = couleur;
            
            javax.swing.text.Style style = doc.addStyle(this.couleur.toString(), null);
            // Foreground color
            StyleConstants.setForeground(style, this.couleur);
            // Append to document
            doc.insertString(doc.getLength(), chaine+"\n", style);
        } catch (BadLocationException e) {
            txtPane_console.setText(e.getMessage());
        }
        //on réinitialise la couleur 
        this.couleur = Color.black;
        StyleConstants.setForeground(doc.addStyle(this.couleur.toString(), null), this.couleur);
        
    }

    public void exit() {
        System.exit(0);
    }

    /**
     * Méthode à implémenter pour étendre l'interface ChangeListener
     * Elle permet de faire scroller les deux ascenceurs en même temps
     * @param ce
     */
    public void stateChanged(ChangeEvent ce) {
        BoundedRangeModel modelScroll_numLigne = sp_numLigne.getVerticalScrollBar().getModel();
        BoundedRangeModel modelScroll_programme = sp_programme.getVerticalScrollBar().getModel();
        if (ce.getSource() == modelScroll_numLigne) {
            modelScroll_programme.setValue(modelScroll_numLigne.getValue());
        } else if (ce.getSource() == modelScroll_programme) {
            modelScroll_numLigne.setValue(modelScroll_programme.getValue());
        }
    }
    public void majAffichageVariable(ModelJTableVariable model_variable) {
        table_variable.setModel(model_variable);
    }
    
    public void setTextConsole(JTextPane txtPane){
        txtPane_console = txtPane;
        System.setOut(new PrintStream(new OutputStreamManager(txtPane_console)));
    }
    
    public JTextPane getTextConsole(){
        return txtPane_console;
    }
    
    public String getTextProgramme(){
        return txtArea_programme.getText();
    }

    
    public void setCodeProgrammeModifie(boolean modifie){
        this.codeModifie = modifie;
    }
    
    public boolean codeModifie(){
        return this.codeModifie;
    }
            
    
    public void majNumLigne() {
        num_ligne.setText("");
        num = 1;
        while (num_ligne.getLineCount() < txtArea_programme.getLineCount()) {
            if (num == 1) {
                num_ligne.setText("" + num);
                num++;
            } else {
                num_ligne.setText(num_ligne.getText() + "\n" + num);
                num++;
            }
        }
    }

    public void afficherErreur(String message) {
        this.ajouterLigneConsole(message, Color.red);
    }

    public void clear() {
        txtPane_console.setText("");
    }
}
